<template>
   <!-- 上传图片 -->
   <div>
      <!-- list-type  文件列表的类型  改变为照片墙的模式
      limit 最大允许上传个数
      给action 一个 # 就不会报错了  必选参数，上传的地址
      on-preview 点击文件列表中已上传的文件时的钩子  预览，预览就是 fileList 中的 放大镜
      file-list 是上传的文件列表，可以绑定到上传组件上，让上传组件来显示
      on-remove 文件列表移除文件时的钩子
      on-change 文件状态改变时的钩子，添加文件、上传成功和上传失败时都会被调用
      before-upload	上传文件之前的钩子，参数为上传的文件，
      若返回 false 或者返回 Promise 且被 reject，则停止上传。
      http-request  覆盖默认的上传行为，可以自定义上传的实现
      -->
      <!-- upload组件显示的是 fileList 的内容 -->
      <el-upload
         list-type="picture-card"
         :limit="1"
         action="#"
         :on-preview="preview"
         :file-list="fileList"
         :class="{ disabled: fileComputed }"
         :on-remove="handleRemove"
         :on-change="changeFile"
         :before-upload="beforeUpload"
         :http-request="upload"
      >
         <!-- :class="{ disabled: fileComputed }" 只有当 fileComputed 为true 时才会显示 -->
         <i class="el-icon-plus"></i>
      </el-upload>
      <!-- percentage属性 : 表示进度条对应的百分比，必填,在 0- 100之间 -->
      <el-progress
         style="width:180px"
         :percentage="percent"
         v-if="showPercent"
      ></el-progress>
      <!-- sync 修饰符，变量在 data 中可代替关闭 -->
      <!-- 图片预览的弹层 -->
      <el-dialog :visible.sync="showDialog" title="图片预览">
         <img :src="imgUrl" alt="" style="width: 100%" />
      </el-dialog>
   </div>
</template>

<script>
// 引入腾讯云cos包
import COS from 'cos-js-sdk-v5'
// 实例化 cos 对象,得到的这个cos 对象就是后边上传所需要的
const cos = new COS({
   // 身份识别 ID
   SecretId: 'AKIDf8MQJwINBjzznPkoiU8YkfJgmb9RSCfr',
   // 身份秘钥
   SecretKey: 'wbz6wVnoXzA4h26tQhgOqZ2E9nAF9pFO'
})
export default {
   data() {
      return {
         // 图片地址设置为数组 ，渲染页面
         // 例：[{name: 'food.jpg', url: 'https://xxx.cdn.com/xxx.jpg'}]
         fileList: [],
         // 图片预览的弹层
         showDialog: false,
         // 保存 图片 地址
         imgUrl: '',
         // 记录当前正在上传的uid
         currentFileUid: null,
         // 当前的进度条百分比
         percent: 0,
         // 控制上传的进度条
         showPercent: false
      }
   },
   computed: {
      fileComputed() {
         // 如果他为 true 表示就不应该显示加号
         return this.fileList.length === 1
      }
   },
   methods: {
      // 点击预览触发事件
      preview(file) {
         // console.log(file.url)
         this.imgUrl = file.url
         this.showDialog = true
      },
      // 删除图片之后显示 + 号的框框
      handleRemove(file, fileList) {
         // file要删除的文件
         // console.log(file)
         // fileList删过之后的文件，删除完之后是一个空数组
         // console.log(fileList)
         // 上边已经删除，这个没有变化，需要根据上边的两个参数变化而变化，再渲染
         // console.log(this.fileList)
         // 将当前的删除的文件排除在外  得到一个新数组
         // 条件成功之后 this.fileList 是一个空数组，因为原来只有一个，再排除掉
         // this.fileList = this.fileList.filter(
         //    item => item.uid !== file.uid
         // )
         this.fileList = fileList
      },
      // 添加文件到 fileList 中，渲染，不能用 push 因为这个钩子会执行多次
      // 添加文件时执行一次，上传文件成功时执行一次
      changeFile(file, fileList) {
         // file 是当前的文件
         // console.log(file)
         // fileList 是当前的点击上传的最新数组，但是这个最新的数组没有改变 this.fileList
         // console.log(fileList)
         // this.fileList 始终没有变过
         // console.log(this.fileList)
         // 第一次是1 第二次是 0
         // console.log(fileList.length)
         // 如果当前fileList中没有该文件，就往里追加
         this.fileList = fileList.map(item => item)
         // 这个暂时上传不成功
         // 因为还没有上传，action 还是个 #，所以第二次进来的数据，一定是个空的
         // 也就是说添加文件是 1，上传文件因为是 # 所以是 0，所以上传失败
         // 如果完成上传动作了，第一次进入和第二次进入的 fileList 的长度应该都是 1，都有数据
         // 没有上传成功，第二次永远是 0
         // 上传成功-->数据才能进来-->腾讯云 cos
      },
      // 上传之前的检查
      beforeUpload(file) {
         // console.log(file)
         // 先检查文件类型
         // 定义文件类型的数组
         const types = [
            'image/jpeg',
            'image/gif',
            'image/bmp',
            'image/png'
         ]
         if (!types.some(item => item === file.type)) {
            // 如果不存在
            this.$message.error('上传图片只能是 JPG、GIF、BMP、PNG 格式!')
            return false
         }
         // 继续检查文件大小  1M = 1024KB  1KB = 1024B
         // 定义文件大小的最大值
         const maxSize = 5 * 1024 * 1024
         if (file.size > maxSize) {
            // 超过了限制的文件大小
            this.$message.error('上传的图片大小不能大于5M')
            return false
         }
         // 如果 都验证过了，不 return true 那么认为你 返回的是 undefined
         // 确定当前上传的就是当前的这个 file，把 file 上传的 uid 记下来
         // console.log(file)
         this.currentFileUid = file.uid
         // 进度条开启
         this.showPercent = true
         return true
      },
      // 上传行为操作
      upload(params) {
         // 通过 params 拿到 file
         // console.log(params.file)
         if (params.file) {
            // 执行上传操作
            // 首先要上传到腾讯云--> 哪个地域的存储桶，文件，格式，回调
            // onProgress	进度的回调函数，进度回调响应对象（progressData）
            cos.putObject(
               {
                  // 存储桶的名称
                  Bucket: 'xuetf-1-1307244531',
                  // 地域名称
                  Region: 'ap-beijing',
                  // 对象在存储桶中的唯一标识，文件名
                  Key: params.file.name,
                  // 要上传的文件对象
                  Body: params.file,
                  // 上传的模式类型，默认标准模式即可
                  StorageClass: 'STANDARD',
                  // onProgress	进度的回调函数，进度回调响应对象（progressData）
                  onProgress: params => {
                     // console.log(params)
                     this.percent = params.percent * 100
                  }
               },
               // 返回结果通过回调函数传给我们
               (err, data) => {
                  // 返回的里边有一个地址，
                  // console.log(err || data)
                  // data 中有一个返回状态
                  // 当它不是错误时，状态码等于 200 时
                  if (!err && data.statusCode === 200) {
                     // 此时说明文件上传成功，要获取成功的返回地址
                     // fileList 才能显示到上传组件上，此时我们要将 fileList
                     // 中的数据的 url 地址，变成现在上传成功的地址
                     // 目前虽然是一张图片，fileList 是一个数组
                     // 需要知道当前上传成功的是哪一张图片
                     // 找数组中谁的 uid 等于上传的 uid
                     // 将上传成功的地址回写到 fileList 中，fileList 变化
                     // --> upload 组件就会根据它的变化而去渲染视图
                     this.fileList = this.fileList.map(item => {
                        if (item.uid === this.currentFileUid) {
                           // 找到之后，把上传成功的地址赋值给原来的url属性
                           return {
                              url: 'http://' + data.Location,
                              upload: true
                           }
                           // upload 为 true 表示这张图片已经上传完毕，这个属性要为我们后期应用的时候做标记
                           // 比如：点击保存按钮，图片有大有小，上传的速度有快有慢，
                           // 要根据有没有upload这个标记来决定是否去保存
                           // 当我们没有上传成功之前是不允许去保存的
                        }
                        // 没找到
                        return item
                     })
                     // 延迟执行
                     setTimeout(() => {
                        // 上传成功之后关闭进度条，重置百分比
                        this.showPercent = false
                        this.percent = 0
                     }, 1000)
                  }
               }
            )
         }
      }
   }
}
</script>

<style>
.disabled .el-upload--picture-card {
   display: none;
}
</style>
